﻿using Autodesk.Revit.DB;
using demo.Extensions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static demo.GeometryCreation;

namespace demo
{
    public class EntityInfo
    {
        /// <summary>
        /// 创建方块
        /// </summary>
        /// <param name="center"></param>
        /// <param name="l"></param>
        /// <returns></returns>
        public Solid CreateBox(XYZ center, double l)
        {
            var LHalf = l / 2;
            List<CurveLoop> curves = new List<CurveLoop>();
            CurveLoop curve = new CurveLoop();
            curve.Append(Line.CreateBound(new XYZ(center.X - LHalf, center.Y - LHalf, center.Z - LHalf), new XYZ(center.X - LHalf, center.Y + LHalf, center.Z - LHalf)));
            curve.Append(Line.CreateBound(new XYZ(center.X - LHalf, center.Y + LHalf, center.Z - LHalf), new XYZ(center.X + LHalf, center.Y + LHalf, center.Z - LHalf)));
            curve.Append(Line.CreateBound(new XYZ(center.X + LHalf, center.Y + LHalf, center.Z - LHalf), new XYZ(center.X + LHalf, center.Y - LHalf, center.Z - LHalf)));
            curve.Append(Line.CreateBound(new XYZ(center.X + LHalf, center.Y - LHalf, center.Z - LHalf), new XYZ(center.X - LHalf, center.Y - LHalf, center.Z - LHalf)));
            curves.Add(curve);
            XYZ extrusiondir = new XYZ(0, 0, 1); // orthogonal
            return GeometryCreation.Instance.CreateExtrusion(curves, extrusiondir, l);
        }

       


        /// <summary>
        /// 创建球型
        /// </summary>
        /// <param name="center">圆心</param>
        /// <param name="radius">半径</param>
        /// <returns></returns>
        public Solid CreateSphere(XYZ center, double radius)
        {
            Frame frame = new Frame(center,XYZ.BasisX,XYZ.BasisY,XYZ.BasisZ);
            List<CurveLoop> curves = new List<CurveLoop>();
            CurveLoop curve = new CurveLoop();
            var ellipse = Ellipse.CreateCurve(center, radius, radius, XYZ.BasisX, XYZ.BasisZ, -Math.PI / 2.0, Math.PI / 2.0);
            curve.Append(ellipse);
            curve.Append(Line.CreateBound(new XYZ(center.X, center.Y, center.Z + radius), new XYZ(center.X, center.Y, center.Z - radius)));
            curves.Add(curve);
            return  GeometryCreationUtilities.CreateRevolvedGeometry(frame, curves, -Math.PI, Math.PI);
        }


        public List<CurveLoop> Profileloops { get; set; }

        /// <summary>
        /// 圆柱体
        /// </summary>
        /// <param name="center"></param>
        /// <param name="bottomradius"></param>
        /// <param name="height"></param>
        /// <param name="cylinderdirection"></param>
        /// <returns></returns>
        public Solid CreateCylinder(XYZ center, double bottomradius, double height, CylinderDirection cylinderdirection)
        {
            double halfheight = height / 2.0;
            XYZ bottomcenter = new XYZ(
               cylinderdirection == CylinderDirection.BasisX ? center.X - halfheight : center.X,
               cylinderdirection == CylinderDirection.BasisY ? center.Y - halfheight : center.Y,
               cylinderdirection == CylinderDirection.BasisZ ? center.Z - halfheight : center.Z);
            XYZ topcenter = new XYZ(
               cylinderdirection == CylinderDirection.BasisX ? center.X + halfheight : center.X,
               cylinderdirection == CylinderDirection.BasisY ? center.Y + halfheight : center.Y,
               cylinderdirection == CylinderDirection.BasisZ ? center.Z + halfheight : center.Z);

            CurveLoop sweepPath = new CurveLoop();
            sweepPath.Append(Line.CreateBound(bottomcenter,topcenter));

            List<CurveLoop> profileloops = new List<CurveLoop>();
            CurveLoop profileloop = new CurveLoop();
            var cemiEllipse1 = Ellipse.CreateCurve(bottomcenter, bottomradius, bottomradius,
               cylinderdirection == CylinderDirection.BasisX ? Autodesk.Revit.DB.XYZ.BasisY : Autodesk.Revit.DB.XYZ.BasisX,
               cylinderdirection == CylinderDirection.BasisZ ? Autodesk.Revit.DB.XYZ.BasisY : Autodesk.Revit.DB.XYZ.BasisZ,
               -Math.PI, 0);
            var cemiEllipse2 = Ellipse.CreateCurve(bottomcenter, bottomradius, bottomradius,
               cylinderdirection == CylinderDirection.BasisX ? Autodesk.Revit.DB.XYZ.BasisY : Autodesk.Revit.DB.XYZ.BasisX,
               cylinderdirection == CylinderDirection.BasisZ ? Autodesk.Revit.DB.XYZ.BasisY : Autodesk.Revit.DB.XYZ.BasisZ,
               0, Math.PI);
            profileloop.Append(cemiEllipse1);
            profileloop.Append(cemiEllipse2);
            profileloops.Add(profileloop);
            Profileloops = Profileloops;
            return GeometryCreationUtilities.CreateSweptGeometry(sweepPath, 0, 0, profileloops);
        }

        /// <summary>
        /// 轮廓沿路径放样生成实体,轮廓垂直于曲线
        /// </summary>
        /// <param name="path"></param>
        /// <param name="options"></param>
        /// <returns></returns>
        public virtual Solid CreateSweptGeometry(CurveLoop path, CurveLoop curveLoop, SolidOptions options)
        {
            int index = (int)Math.Floor(0.5 * (path.Count() - 1));
            Curve curve = path.ElementAt(index);
            double para_nor = 0.5;
            double para_raw = curve.ComputeRawParameter(para_nor);

            Transform transform = TransformUtils.GetTransformVertical(curve, para_nor);
            List<CurveLoop> loops = new List<CurveLoop>();
            if (transform.IsConformal)
            {
                loops.Add(CurveLoop.CreateViaTransform(curveLoop, transform));
               
            }
            return GeometryCreationUtilities.CreateSweptGeometry(path, index, para_raw, loops, options);
        }



        public Solid Intersect(Solid solid1, Solid solid2)
        {
            return BooleanOperationsUtils.ExecuteBooleanOperation(solid1,solid2,BooleanOperationsType.Intersect);
        }

        public Solid Union(Solid solid1, Solid solid2)
        {
            return BooleanOperationsUtils.ExecuteBooleanOperation(solid1, solid2, BooleanOperationsType.Union);
        }
        public Solid Difference(Solid solid1, Solid solid2)
        {
            return BooleanOperationsUtils.ExecuteBooleanOperation(solid1, solid2, BooleanOperationsType.Difference);
        }



    }
}
